#include "ui_rect.h"
#include "ui_error.h"
#include "ui_std_ex.h"
#include <algorithm>


namespace UI
{


SDL_Rect UI_Rect::SDLRect(void) const
{
	SDL_Rect sdlRect;
	sdlRect.x = stdex::safe_static_cast<short int>(std::min(m_Left, m_Right));
	sdlRect.y = stdex::safe_static_cast<short int>(std::min(m_Top, m_Bottom));
	sdlRect.w = stdex::safe_static_cast<short int>(Width());
	sdlRect.h = stdex::safe_static_cast<short int>(Height());

	return sdlRect;
}

UI_Rect& UI_Rect::operator=(const UI_Rect& r)
{
	m_Top = r.Top();
	m_Left = r.Left();
	m_Right = r.Right();
	m_Bottom = r.Bottom();

	return *this;
}


UI_Rect UI_Rect::operator+(const UI_Point& p) const
{
	UI_Rect result(m_Left + p.XPos(), m_Top + p.YPos(), m_Right + p.XPos(), m_Bottom + p.YPos());

	return result;
}


UI_Rect UI_Rect::operator-(const UI_Point& p) const
{
	UI_Rect result(m_Left - p.XPos(), m_Top - p.YPos(), m_Right - p.XPos(), m_Bottom - p.YPos());

	return result;
}


UI_Rect& UI_Rect::Grow(int iGrowAmount)
{
	m_Top -= iGrowAmount;
	m_Left -= iGrowAmount;
	m_Right += iGrowAmount;
	m_Bottom += iGrowAmount;

	return *this;
}


UI_Rect& UI_Rect::Move(int iOffsetX, int iOffsetY)
{
	m_Left += iOffsetX;
	m_Top += iOffsetY;
	m_Right += iOffsetX;
	m_Bottom += iOffsetY;

	return *this;
}


bool UI_Rect::Overlaps(const UI_Rect& r) const
{
	bool bOverlap = false;

	if (m_Right >= r.m_Left && m_Left <= r.m_Right && m_Top <= r.m_Bottom && m_Bottom >= r.m_Top)
	{
		bOverlap = true;
	}

	return bOverlap;
}


UI_Rect& UI_Rect::ClipTo(const UI_Rect& r)
{
	if (! Overlaps(r))
	{
		m_Left = 0;
		m_Top = 0;
		m_Right = 0;
		m_Bottom = 0;
	}
	else
	{
		if (m_Left < r.m_Left)
		{
			m_Left = r.m_Left;
		}
		if (m_Top < r.m_Top)
		{
			m_Top = r.m_Top;
		}
		if (m_Right > r.m_Right)
		{
			m_Right = r.m_Right;
		}
		if (m_Bottom > r.m_Bottom)
		{
			m_Bottom = r.m_Bottom;
		}
	}

	return *this;
}


// test to see if the point lies within the rect
unsigned int UI_Rect::HitTest(const UI_Point& p) const
{
	unsigned int eRelPos = 0;

	eRelPos |= (p.XPos() < m_Left) ? RELPOS_LEFT : 0;
	eRelPos |= (p.YPos() < m_Top) ? RELPOS_ABOVE: 0;
	eRelPos |= (p.XPos() > m_Right) ? RELPOS_RIGHT : 0;
	eRelPos |= (p.YPos() > m_Bottom) ? RELPOS_BELOW: 0;
	eRelPos |= (p.XPos() >= m_Left && p.XPos() <= m_Right &&
		p.YPos() >= m_Top && p.YPos() <= m_Bottom) ? RELPOS_INSIDE : 0;

	return eRelPos;
}

}

